package com.wanghaibo.vgashow.climatecontrol;

import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.wanghaibo.vgashow.R;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * TODO: document your custom view class.
 */
public class WindView extends View {
    private static final float ROTATE_X_DEGREE_MIN = 70.0f;
    private static final float ROTATE_X_DEGREE_MAX = 100.0f;
    private static final float SKEW_X_TAN_MIN = -0.2f;
    private static final float SKEW_X_TAN_MAX = 0.2f;

    private static final int PARTICLE_MAX_NUM = 30;

    private int height, width;
    private Paint windPaint;
    private Paint indicatorLinePaint;
    private Paint indicatorPointPaint;
    private Matrix mMatrix;
    private Camera mCamera;
    private Bitmap windBitmap;
    //双缓冲绘图
    private Paint blurPaint;
    private int blurRadius = 20;
    private Bitmap bufferBitmap;
    private Canvas bufferCanvas;

    private int bitmapWidth, bitmapHeight;
    // 横向、纵向控制系数，0~100间整数，用于绘制UI，随用户拖动一直变
    private int windX;
    private int windY;
    // 点击触屏时的x、y坐标
    private float downX;
    private float downY;
    private boolean isTouching;

    private onWindXYChangedListener onWindXYChangedListener;

    //粒子系统
    private Random mRandom = new Random(123);
    //粒子发射区域
    private RectF emitterRectF;
    //粒子列表
    private List<AnimParticle> mParticleList = new ArrayList<>(PARTICLE_MAX_NUM);
    private ValueAnimator mParticleListAnimator;
    //粒子画笔
    private Paint mPointPaint;
    //粒子方向
    private double direction;

    //是否在自动扫风
    private boolean isXSwingFlap = false;
    private boolean isYSwingFlap = false;
    //自动扫风频率
    private int xSwingFlapPeriod = 1000;
    private int ySwingFlapPeriod = 1000;

    public void setOnWindXYChangedListener(com.wanghaibo.vgashow.climatecontrol.WindView.onWindXYChangedListener onWindXYChangedListener) {
        this.onWindXYChangedListener = onWindXYChangedListener;
    }


    public WindView(Context context) {
        super(context);
        init(null, 0);
    }

    public WindView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public WindView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//        initWind();
//        initAnimParticle();
        indicatorLinePaint = new Paint();
        indicatorLinePaint.setStyle(Paint.Style.STROKE);
        indicatorLinePaint.setStrokeCap(Paint.Cap.ROUND);
        indicatorLinePaint.setStrokeWidth(4);
        indicatorLinePaint.setColor(Color.BLACK);
        indicatorLinePaint.setAlpha((int) (255 * 0.2));

        indicatorPointPaint = new Paint();
        indicatorPointPaint.setStyle(Paint.Style.FILL);
        indicatorPointPaint.setColor(Color.WHITE);
        //投影效果
        indicatorPointPaint.setMaskFilter(new BlurMaskFilter(2, BlurMaskFilter.Blur.SOLID));
    }

    private void initWind() {
        windX = 50;
        windY = 50;
        isTouching = false;
        windPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        windBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.wind);
        bitmapWidth = windBitmap.getWidth();
        bitmapHeight = windBitmap.getHeight();
        mMatrix = new Matrix();
        mCamera = new Camera();

        blurPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        blurPaint.setMaskFilter(new BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL));

    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //双缓冲绘图，为了模糊掉被画布裁掉的硬边
        bufferBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bufferCanvas = new Canvas(bufferBitmap);
        drawBufferBitmap();
        canvas.drawBitmap(bufferBitmap, null, new RectF(blurRadius, blurRadius, width - blurRadius, height - blurRadius), blurPaint);

        //当触摸时，绘制指示条
        if (isTouching) {
            canvas.drawLines(new float[]{8, 8, 8, height - 16, 16, height - 8, width - 8, height - 8}, indicatorLinePaint);
            canvas.drawCircle(8, 8 + (100 - windY) / 100f * (height - 24), 8, indicatorPointPaint);
            canvas.drawCircle(16 + windX / 100f * (width - 24), height - 8, 8, indicatorPointPaint);
        }
        //如果开启了自动扫风，根据给定周期和当前毫秒数计算摆动位置
        if (isXSwingFlap) {
            windX = (int) Math.abs(System.currentTimeMillis() % xSwingFlapPeriod * 200 / xSwingFlapPeriod - 100);
        }
        if (isYSwingFlap) {
            windY = (int) Math.abs(System.currentTimeMillis() % ySwingFlapPeriod * 200 / ySwingFlapPeriod - 100);
        }

    }

    private void drawBufferBitmap() {
        //画风，图层叠加做出体积感j
        for (int i = -4; i < 8; i++) {
            mCamera.save();
            mCamera.rotateX(-0.5f * i - 3 + windY * (ROTATE_X_DEGREE_MAX - ROTATE_X_DEGREE_MIN) / 100.0f + ROTATE_X_DEGREE_MIN);
            mCamera.getMatrix(mMatrix);
            mCamera.restore();

            mMatrix.preSkew(windX * (SKEW_X_TAN_MAX - SKEW_X_TAN_MIN) / 100.0f + SKEW_X_TAN_MIN, 0);
            mMatrix.preTranslate(-0.5f * width / 2.0f, -1.4f * height / 2.0f);
            mMatrix.preScale(0.5f * width / bitmapWidth, 1.4f * height / bitmapHeight);
            mMatrix.postTranslate(width / 2.0f, height / 2.0f);

            windPaint.setAlpha(255 / 3);
            bufferCanvas.drawBitmap(windBitmap, mMatrix, windPaint);
        }
        //计算粒子的方向
        direction = (windY == 50 && windX == 50) ? -Math.PI / 2 : Math.atan2(windY - 100 / 2f, 100 / 2f - windX);

        //画运动粒子
        for (AnimParticle animParticle : mParticleList) {
            mPointPaint.setAlpha(animParticle.getAlpha());
            bufferCanvas.drawCircle(animParticle.getmX(), animParticle.getmY(),
                    animParticle.getRadius(), mPointPaint);
        }
        invalidate();
    }

    /**
     * 初始化动画
     */
    private void initAnimParticle() {
        //初始化运动粒子的画笔
        mPointPaint = new Paint();
        mPointPaint.setColor(Color.WHITE);
        direction = Math.toRadians(270);//粒子方向初始化：向下
        //粒子羽化效果
        mPointPaint.setMaskFilter(new BlurMaskFilter(2, BlurMaskFilter.Blur.NORMAL));
        //绘制运动的粒子
        mParticleList.clear();
        AnimParticle mAnimParticle = new AnimParticle();
        for (int i = 0; i < PARTICLE_MAX_NUM; i++) {
            //通过clone创建对象，避免重复创建
            AnimParticle cloneAnimParticle = mAnimParticle.clone();
            //先给每个粒子初始化各类属性
            cloneAnimParticle.init(mRandom, emitterRectF);
            mParticleList.add(cloneAnimParticle);
        }
        //画运动粒子
        mParticleListAnimator = ValueAnimator.ofFloat(0F, 1F);
        mParticleListAnimator.setDuration(Integer.MAX_VALUE);
        mParticleListAnimator.setRepeatMode(ValueAnimator.RESTART);
        mParticleListAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mParticleListAnimator.addUpdateListener(animation -> {
            for (AnimParticle point : mParticleList) {
                //通过属性动画不停的计算下粒子的下一个坐标
                point.updateParticle(mRandom, emitterRectF, direction);
            }
            invalidate();
        });
        mParticleListAnimator.start();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        height = getHeight();
        width = getWidth();
        downX = width * 0.5f;
        downY = height * 0.5f;
        initWind();
        //初始化发射器位置
        emitterRectF = new RectF(0.25f * width, 0.45f * height, 0.75f * width, 0.55f * height);
        initAnimParticle();
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mParticleListAnimator != null) {
            if (mParticleListAnimator.isStarted()) {
                mParticleListAnimator.cancel();
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isYSwingFlap && !isXSwingFlap) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isTouching = true;
                    onWindXYChangedListener.onWindXYChangeStart(windX, windY);
                    //继续执行，不要加break
                case MotionEvent.ACTION_MOVE:
                    //计算风的X、Y
                    downX = event.getX();
                    downY = event.getY();
                    if (downX > width) {
                        downX = width;
                    } else if (downX < 0) {
                        downX = 0;
                    }
                    if (downY < 0) {
                        downY = 0;
                    } else if (downY > height) {
                        downY = height;
                    }
                    windX = (int) (downX / width * 100f);
                    windY = (int) ((1 - downY / height) * 100f);
//                    //计算粒子的方向
//                    direction = Math.atan2(height / 2f - downY, width / 2f - downX);
                    break;
                case MotionEvent.ACTION_UP:
                    isTouching = false;
                    onWindXYChangedListener.onWindXYConfirmed(this, windX, windY);
                default:
                    break;
            }
        }
        return true;
    }

    /**
     * 开始自动扫风
     *
     * @param xSwingFlap    是否开启横向扫风
     * @param ySwingFlap    是否开启纵向扫风
     * @param xPeriodMillis 横向扫风周期（毫秒）
     * @param yPeriodMillis 纵向扫风周期（毫秒）
     */
    public void swingFlapStart(boolean xSwingFlap, boolean ySwingFlap, int xPeriodMillis, int yPeriodMillis) {
        xSwingFlapPeriod = xPeriodMillis;
        isXSwingFlap = xSwingFlap;
        ySwingFlapPeriod = yPeriodMillis;
        isYSwingFlap = ySwingFlap;
    }

    public void swingFlapStop() {
        isXSwingFlap = false;
        isYSwingFlap = false;
    }

    public int getWindX() {
        return windX;
    }

    public void setWindX(int windX) {
        this.windX = windX;
    }

    public int getWindY() {
        return windY;
    }

    public void setWindY(int windY) {
        this.windY = windY;
    }

    public void confirmWindXY(int[] windXY) {
        this.windX = windXY[0];
        this.windY = windXY[1];
        onWindXYChangedListener.onWindXYConfirmed(this, windX, windY);
    }

    //出风口方向变化监听器
    public interface onWindXYChangedListener {
        /**
         * 出风口方向开始变化
         *
         * @param windX 横向控制系数，0~100间整数
         * @param windY 纵向控制系数，0~100间整数
         */
        void onWindXYChangeStart(int windX, int windY);

        /**
         * 出风口方向确定
         *
         * @param windView windView本身
         * @param windX    横向控制系数，0~100间整数
         * @param windY    纵向控制系数，0~100间整数
         */
        void onWindXYConfirmed(com.wanghaibo.vgashow.climatecontrol.WindView windView, int windX, int windY);
    }


}
